/// Copyright (c) 2008 Brad Williams
/// 
/// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
/// associated documentation files (the "Software"), to deal in the Software without restriction,
/// including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
/// and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
/// subject to the following conditions:
/// 
/// The above copyright notice and this permission notice shall be included in all copies or substantial
/// portions of the Software.
/// 
/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
/// NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
/// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
/// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
/// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading;
using Db4objects.Db4o;
using Db4objects.Db4o.Ext;
using Db4objects.Db4o.Query;

namespace db4oProviders
{
    /// <summary>
    /// Serializes the lifetimes of IObjectContainer objects per connection string.
    /// </summary>
    public class SafeDB : IObjectContainer
    {
        private IObjectContainer db;
        private Mutex mutex;

        public SafeDB(string connectionString)
        {
            mutex = new Mutex(false, GetType() + connectionString.GetHashCode().ToString());
            mutex.WaitOne();
            db = Db4oFactory.OpenFile(connectionString);
        }

        #region IObjectContainer Members

        public void Dispose()
        {
            db.Dispose();
            db = null;
            mutex.ReleaseMutex();
            mutex = null;
        }

        #region IObjectContainer delegations

        public void Activate(object obj, int depth)
        {
            db.Activate(obj, depth);
        }

        public bool Close()
        {
            return db.Close();
        }

        public void Commit()
        {
            db.Commit();
        }

        public void Deactivate(object obj, int depth)
        {
            db.Deactivate(obj, depth);
        }

        public void Delete(object obj)
        {
            db.Delete(obj);
        }

        public IExtObjectContainer Ext()
        {
            return db.Ext();
        }

        [Obsolete("Use QueryByExample instead")]
        public IObjectSet Get(object template)
        {
#pragma warning disable 612,618
            return db.Get(template);
#pragma warning restore 612,618
        }

        public IObjectSet QueryByExample(object template)
        {
            return db.QueryByExample(template);
        }

        public IQuery Query()
        {
            return db.Query();
        }

        public IObjectSet Query(Type clazz)
        {
            return db.Query(clazz);
        }

        public IObjectSet Query(Predicate predicate)
        {
            return db.Query(predicate);
        }

        public IObjectSet Query(Predicate predicate, IQueryComparator comparator)
        {
            return db.Query(predicate, comparator);
        }

        public IObjectSet Query(Predicate predicate, IComparer comparer)
        {
            return db.Query(predicate, comparer);
        }

        public void Rollback()
        {
            db.Rollback();
        }

        [Obsolete("Use Store instead")]
        public void Set(object obj)
        {
#pragma warning disable 612,618
            db.Set(obj);
#pragma warning restore 612,618
        }

        public void Store(object obj)
        {
            db.Store(obj);
        }

        public IList<Extent> Query<Extent>(Predicate<Extent> match)
        {
            return db.Query(match);
        }

        public IList<Extent> Query<Extent>(Predicate<Extent> match, IComparer<Extent> comparer)
        {
            return db.Query(match, comparer);
        }

        public IList<Extent> Query<Extent>(Predicate<Extent> match, Comparison<Extent> comparison)
        {
            return db.Query(match, comparison);
        }

        public IList<ElementType> Query<ElementType>(Type extent)
        {
            return db.Query<ElementType>(extent);
        }

        public IList<Extent> Query<Extent>()
        {
            return db.Query<Extent>();
        }

        public IList<Extent> Query<Extent>(IComparer<Extent> comparer)
        {
            return db.Query(comparer);
        }

        #endregion

        #endregion
    }
}
